﻿using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace FreeRobot.Common
{
    class CSharpCode : IDisposable
    {
        readonly CSharpCodeProvider _codeProvider;
        readonly ICodeCompiler _icc;
        readonly System.CodeDom.Compiler.CompilerParameters _parameters;
        readonly string _outName;
        public CSharpCode(string outName)
        {
            _codeProvider = new CSharpCodeProvider();
            _icc = _codeProvider.CreateCompiler();
            _parameters = new CompilerParameters();
            _parameters.GenerateExecutable = true;
            _parameters.OutputAssembly = outName;
            _outName = outName;
        }
        public event Action<CompilerResults> ResultsCallback;
        public event Action<CompilerResults, CompilerErrorCollection> ErrorCallback;
        public event Action<string> SuccessCallback;
        public void Excute(string code)
        {
            Kill();
            CompilerResults results = _icc.CompileAssemblyFromSource(_parameters, code);
            if (ResultsCallback != null)
                ResultsCallback(results);
            if (results.Errors.Count > 0)
            {
                if (ErrorCallback != null)
                {
                    ErrorCallback(results, results.Errors);
                }
                foreach (CompilerError CompErr in results.Errors)
                {
                    var err =
                                "Line number " + CompErr.Line +
                                ", Error Number: " + CompErr.ErrorNumber +
                                ", '" + CompErr.ErrorText + ";";
                    Trace.WriteLine(err);
                }
            }
            else
            {
                Process process = new Process();
                process.StartInfo.FileName = _outName;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.CreateNoWindow = true;
                process.Start();
                // 读取输出
                string output = process.StandardOutput.ReadToEnd();
                process.Dispose();
                if (SuccessCallback != null)
                    SuccessCallback(output);
            }
        }
        public void Kill()
        {
            var p = Process.GetProcessesByName(_outName.Substring(0, _outName.LastIndexOf(".")));
            if (p.Length > 0)
                p.First().Kill();
        }
        public void Dispose()
        {
            _codeProvider.Dispose();
        }
    }
}
